﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Entities;

namespace Metier
{
    public class GestionCommande
    {
        GestionPreparationPlat gestionPreparationPlat = new GestionPreparationPlat();
        GestionPlat gestionPlat = new GestionPlat();
        GestionNotification gestionNotification = new GestionNotification();

        public void nouvelleCommande(Commande commande)
        {
            try
            {
                Ajouter(commande);

                TypePlat headPlat = commande.getEtatCommande();
                List<Plat> PlatMemeType = new List<Plat>();

                foreach (Plat plat in commande.Plat)
                {
                    using (Context db = new Context())
                    {
                        //A verif :) il est 5h et jvous emmerde

                        PlatMemeType = (from p in commande.Plat
                                        where p.getType() == headPlat
                                        select p).ToList();
                        /* Donc ici on est sensé obtenir une liste objet plat qui correspond 
                            * a la commande par type (entree/plat ou desser)*/
                        break;
                    }

                }
                if (PlatMemeType.Count != 0)
                {
                    foreach (Plat plat in PlatMemeType)
                    {
                        PreparationPlat platSuivants = new PreparationPlat();
                        platSuivants.setType(EtatPlat.EnAttenteCuisine);
                        platSuivants.Plat = plat;
                        platSuivants.Commande = commande;

                        gestionPreparationPlat.Ajouter(platSuivants);


                        Notification notif = new Notification();
                        notif.Commande = commande;
                        notif.PreparationPlat = platSuivants;
                        notif.setType(TypeNotification.PlatSuivant);
                        notif.Fait = false;

                        gestionNotification.Ajouter(notif);
                    }
                }
            }
            catch (ArgumentNullException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        public void platSuivant(Commande commande)
        {
            try
            {
                /*
                 * Ici on regarde l'état actuel de la commande pour le mettre à jour
                 */
                TypePlat currentType = commande.getEtatCommande();
                switch (currentType)
                {
                    case TypePlat.Entrée:
                        commande.setEtatCommande(TypePlat.PlatPrincipal);
                        break;
                    case TypePlat.PlatPrincipal:
                        commande.setEtatCommande(TypePlat.Dessert);
                        break;
                    default:
                        commande.setEtatCommande(TypePlat.Autres);
                        break;

                }

                /*
                 * Ici on envoi les plats suivants contenus dans la commande
                 */
                currentType = commande.getEtatCommande();
                List<Plat> PlatSuivantType = new List<Plat>();

                foreach (Plat plat in commande.Plat)
                {
                    using (Context db = new Context())
                    {
                        PlatSuivantType = (from p in commande.Plat
                                           where p.getType() == currentType
                                           select p).ToList();

                        break;
                    }

                }

                /*
                 * Selon la liste obtenue, on envoi la liste des plats en liste /notif
                 * Sinon on relance cette methode jusqu'a ce qu'on arrive a l'état "autre"
                 */
                if (PlatSuivantType.Count != 0)
                {
                    foreach (Plat plat in PlatSuivantType)
                    {
                        PreparationPlat platSuivants = new PreparationPlat();
                        platSuivants.setType(EtatPlat.EnAttenteCuisine);
                        platSuivants.Plat = plat;
                        platSuivants.Commande = commande;

                        gestionPreparationPlat.Ajouter(platSuivants);


                        Notification notif = new Notification();
                        notif.PreparationPlat = platSuivants;
                        notif.setType(TypeNotification.PlatSuivant);
                        notif.Fait = false;

                        gestionNotification.Ajouter(notif);
                    }
                }
                else
                {
                    if (currentType == TypePlat.Autres)
                    {
                        // Action Regler commande ? changer ihm pour passer au paiement? Proposer café?
                    }
                    else
                    {
                        platSuivant(commande);
                    }
                }
            }
            catch (ArgumentNullException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        public void reglerCommande(Commande commande)
        {
            commande.EstRegle = true;
            MettreAJour(commande);
        }

        public List<Commande> Lister(string mailUtilisateur)
        {
            try
            {
                using (Context db = new Context())
                {
                    return (from c in db.Commandes
                            where c.Serveur.Email == mailUtilisateur
                            select c).ToList();
                }
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        #region Ressources

        void Ajouter(Commande commande)
        {
            try
            {
                using (Context db = new Context())
                {
                    db.Commandes.AddObject(commande);
                    db.SaveChanges();
                }
            }
            catch (ArgumentNullException ex)
            {
                throw new Exception("Erreur db : Echec Ajout : Commande est null", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Erreur db : Echec Ajout Commande avec l'id : " + commande.Id, ex);
            }
        }

        List<Commande> Lister()
        {
            try
            {
                using (Context db = new Context())
                {
                    return db.Commandes.ToList();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Erreur Repository : Echec Recuperation toutes les Commandes", ex);
            }
        }

        List<Commande> Lister(bool commandeReglee)
        {
            try
            {
                if (commandeReglee == true)
                {
                    using (Context db = new Context())
                    {
                        return (from c in db.Commandes
                                where c.EstRegle == commandeReglee
                                select c).ToList();
                    }

                }
                else
                {
                    using (Context db = new Context())
                    {
                        return (from c in db.Commandes
                                where c.EstRegle == false
                                select c).ToList();
                    }
                }

            }
            catch (Exception ex)
            {
                throw new Exception("Erreur Repository : Echec Recuperation toutes les Commandes reglees ou non", ex);
            }
        }

        Commande TrouverCommande(Table table)
        {
            try
            {
                using (Context db = new Context())
                {
                    return (from c in db.Commandes
                            where c.Table.Id == table.Id
                            select c).FirstOrDefault();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Erreur Repository : Echec Recuperation Commande avec table : " + table, ex);
            }
        }

        void MettreAJour(Commande commande)
        {
            try
            {
                using (Context db = new Context())
                {
                    db.Commandes.Attach(commande);
                    db.ObjectStateManager.ChangeObjectState(commande, System.Data.EntityState.Modified);
                    db.SaveChanges();
                }
            }
            catch (ArgumentNullException ex)
            {
                throw new Exception("Erreur Repository : Echec Mise a jour Commande : nouvelle Commande est null", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Erreur Repository : Echec Mise a jour Commande avec l'id : " + commande.Id, ex);
            }
        }

        public void Supprimer(Commande commande)
        {
            try
            {
                using (Context db = new Context())
                {
                    db.Commandes.DeleteObject(commande);
                    db.SaveChanges();
                }
            }
            catch (ArgumentNullException ex)
            {
                throw new Exception("Erreur Repository : Echec Suppression Commande : Commande est null", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Erreur Respository : Echec Suppression Commande avec l'id : " + commande.Id, ex);
            }
        }
        #endregion
    }
}
